/**
 * Copyright (c) 2016-2019, Michael Yang 杨福海 (fuhai999@gmail.com).
 * <p>
 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl-3.0.txt
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.jpress.module.article.service.provider;

import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import io.jboot.aop.annotation.Bean;
import io.jboot.db.model.Column;
import io.jboot.db.model.Columns;
import io.jboot.service.JbootServiceBase;
import io.jpress.commons.utils.SqlUtils;
import io.jpress.module.article.model.Article;
import io.jpress.module.article.model.ArticleComment;
import io.jpress.module.article.service.ArticleCommentService;
import io.jpress.module.article.service.ArticleService;
import io.jpress.module.article.service.task.CommentReplyCountUpdateTask;
import io.jpress.service.UserService;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.List;

@Bean
@Singleton
public class ArticleCommentServiceProvider extends JbootServiceBase<ArticleComment> implements ArticleCommentService {

    @Inject
    private ArticleService articleService;

    @Inject
    private UserService userService;


    @Override
    public ArticleComment findById(Object id) {
        ArticleComment comment = super.findById(id);
        articleService.join(comment, "article_id");
        userService.join(comment, "user_id");
        return comment;
    }

    @Override
    public ArticleComment findByPid(Object pid) {
        ArticleComment comment = DAO.findFirstByColumn(Column.create("pid",pid));
//        articleService.join(comment, "article_id");
//        userService.join(comment, "user_id");
        return comment;
    }

    @Override
    public boolean deleteByIds(Object... ids) {
        for (Object id : ids) {
            deleteById(id);
        }
        return true;
    }

    @Override
    public boolean deleteById(Object id) {
        ArticleComment comment = findById(id);
        if (comment == null) {
            return false;
        }

        boolean delOK = super.deleteById(id);
        if (delOK && comment.getArticleId() != null) {
            articleService.doUpdateCommentCount(comment.getArticleId());
        }
        return delOK;
    }

    @Override
    public boolean batchChangeStatusByIds(String status, Object... ids) {
        return Db.update("update article_comment SET `status` = ? where id in  " + SqlUtils.buildInSqlPara(ids), status) > 0;
    }

    @Override
    public Page<ArticleComment> paginate(int page, int pageSize) {
        Page p = super.paginate(page, pageSize);
        articleService.join(p, "article_id");
        userService.join(p, "user_id");
        return p;
    }


    @Override
    public List<ArticleComment> findListByColumns(Columns columns, String orderBy, Integer count) {
        List<ArticleComment> list = DAO.findListByColumns(columns, orderBy, count);
        articleService.join(list, "article_id");
        userService.join(list, "user_id");
        return list;
    }

    @Override
    public boolean doChangeStatus(long id, String status) {
        ArticleComment comment = findById(id);
        comment.setStatus(status);
        return comment.update();
    }

    @Override
    public long findCountByStatus(String status) {
        return Db.queryLong("select count(*) from article_comment where status = ?", status);
    }

    @Override
    public long findCountByArticleId(Long articleId) {
        return Db.queryLong("select count(*) from article_comment where article_id = ?", articleId);
    }

    @Override
    public long findCountByArticleIdAndStatus(Long articleId,String status){
        return Db.queryLong("select count(*) from article_comment where article_id = ? and status = ?", articleId,status);
    }


    @Override
    public Page<ArticleComment> _paginateByStatus(int page, int pagesize, Long articleId, String keyword, String status) {

        Columns columns = Columns.create("article_id", articleId)
                .add("status", status).is_null("pid")
                .likeAppendPercent("content", keyword);

        Page<ArticleComment> p = DAO.paginateByColumns(page,
                pagesize,
                columns,
                "order_number desc,id desc");

        userService.join(p, "user_id");
        articleService.join(p, "article_id");
        return p;
    }


    @Override
    public Page<ArticleComment> _paginateWithoutTrash(int page, int pagesize, Long articleId, String keyword) {

        Columns columns = Columns.create("article_id", articleId)
                .ne("status", ArticleComment.STATUS_TRASH).is_null("pid")
                .likeAppendPercent("content", keyword);

        Page<ArticleComment> p = DAO.paginateByColumns(
                page,
                pagesize,
                columns,
                "order_number desc,id desc");


        userService.join(p, "user_id");
        articleService.join(p, "article_id");
        return p;
    }

    @Override
    public Page<ArticleComment> _paginateByUserId(int page, int pagesize, long userId) {
        Page<ArticleComment> p = DAO.paginateByColumn(page, pagesize, Column.create("user_id", userId), "id desc");
        articleService.join(p, "article_id");
        return p;
    }

    @Override
    public Page<ArticleComment> commentReplyPaginate(int page, int pageSize, Long userId) {
        Columns columns = Columns.create("user_id", userId);
        columns.is_not_null("pid");
        Page<ArticleComment> p = DAO.paginateByColumns(
                page,
                pageSize,
                columns,
                "order_number desc,id desc");
        join(p,"pid","parent");
        articleService.join(p,"article_id");
        return p;
    }

    @Override
    public Page<ArticleComment> paginateByArticleIdInNormal(int page, int pagesize, long articleId) {
        Columns columns = Columns.create("article_id", articleId);
        columns.add("status", ArticleComment.STATUS_NORMAL);
        columns.is_null("pid");

        Page<ArticleComment> p = DAO.paginateByColumns(
                page,
                pagesize,
                columns,
                "order_number desc,id desc");
        joinAuthorReply(p);
        joinParentUser(p);
        userService.join(p, "user_id");

        return p;
    }

    private void joinAuthorReply(Page<ArticleComment> p) {
        if (p == null || p.getList().isEmpty()) {
            return;
        }
        for (ArticleComment articleComment : p.getList()) {
            articleComment.put("authorReply",findByPid(articleComment.getId()));
        }
    }

    @Override
    public Page<ArticleComment> paginateCommentsReceive(int page,int pagesize,Long userId){
        StringBuilder sqlBuilder = new StringBuilder(" from article_comment c ");
        sqlBuilder.append(" inner join article a on(a.id = c.article_id and c.pid is null) ");
        Columns columns = new Columns();
        columns.add("a.user_id",userId);
        SqlUtils.appendWhereByColumns(columns, sqlBuilder);
        sqlBuilder.append(" order by c.id desc ");
        Page<ArticleComment> dataPage = DAO.paginate(page, pagesize, "select c.*,a.id as articleId ,a.title as articleTitle,a.thumbnail as articleThumbnail", sqlBuilder.toString(), columns.getValueArray());
        userService.join(dataPage,"user_id");
        joinAuthorReply(dataPage);
        return dataPage;
    }

    @Override
    public Page<ArticleComment> paginateCommentsSend(int page,int pagesize,Long userId){
        StringBuilder sqlBuilder = new StringBuilder(" from article_comment c inner join article_comment reply inner join article a on (c.id=reply.pid and reply.pid is not null and c.article_id=a.id) ");
        Columns columns = new Columns();
        columns.add("c.user_id",userId);
        SqlUtils.appendWhereByColumns(columns, sqlBuilder);
        sqlBuilder.append(" order by reply.id desc ");
        Page<ArticleComment> dataPage = DAO.paginate(page, pagesize, "select c.*,reply.content as replyContent,reply.author as replyAuthor,a.id as article_id ,a.title as article_title,a.thumbnail as article_thumbnail,a.user_id as article_user_id", sqlBuilder.toString(), columns.getValueArray());
        userService.join(dataPage,"article_user_id","article_user");
        return dataPage;
    }

    private void joinParentUser(Page<ArticleComment> p) {
        if (p == null || p.getList().isEmpty()) {
            return;
        }

        for (ArticleComment articleComment : p.getList()) {
            userService.join((ArticleComment) articleComment.get("parent"), "user_id");
        }
    }


    @Override
    public void doIncCommentReplyCount(long commentId) {
        CommentReplyCountUpdateTask.recordCount(commentId);
    }

    @Override
    public boolean isOwn(ArticleComment comment, long userId) {
        if (comment.getId() == null) {
            return true;
        }

        if (comment == null || comment.getUserId() == null) {
            return false;
        }
        return comment.getUserId().equals(userId);
    }


}
